#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>

#define BUFSIZE 128
#define CNT     10
#define CPS   10 // 每秒产生令牌的数量
#define BURST	((CPS) * 10) // 上限

int mycpy_sysio(int rfd, int wfd);
static void sig_handler(int sig);

static int token;

int main(int argc, char **argv)
{
    int fd1;

    if (argc < 2)
        return 1;

    fd1 = open(argv[1], O_RDONLY); // 只读的方式打开文件1
    if (-1 == fd1) {
        // 打印失败的原因

		perror("提示词，open()函数调用失败："); // 直接打印失败的原因
        return -1;
    }

    mycpy_sysio(fd1, 1);

    close(fd1);
    return 0;
}

int mycpy_sysio(int rfd, int wfd)
{
    char buf[BUFSIZE] = {0};
    int cnt;
    struct sigaction act = {};
    struct sigaction oldact;
    struct itimerval itv, olditv;

    /* 控制I/O流量 */
    // 注册信号
    act.sa_handler = sig_handler;
    sigaction(SIGALRM, &act, &oldact);

    // 定时触发信号
    itv.it_interval.tv_sec = 1; // 循环定时时间
    itv.it_interval.tv_usec = 0;
    itv.it_value.tv_sec = 3; // 初始触发时间
    itv.it_value.tv_usec = 0;
    setitimer(ITIMER_REAL, &itv, &olditv);

    while (1) {
        // 控制流量
        while (token < CNT) // token小于一次的消耗量
            pause();

        token -= CNT; // 减少token

        cnt = read(rfd, buf, CNT);

        if (0 == cnt) {
            break;
        } else if (-1 == cnt) {
            perror("read()");
            return -1;
        }

        write(wfd, buf, cnt);
        memset(buf, 0, BUFSIZE);
    }
    return 0;
}


static void sig_handler(int sig)
{
    token += CPS; // 信号到来token增加
    token = token > BURST ? BURST : token; // 不能超过上限
}

